package com.ht.api.db.hlink.filter;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;

/**
 * JSON条件评估器
 * @author asq
 * @createTime 2024年12月12日 22:00:30
 */
@Slf4j
public class JsonConditionEvaluator {
    
    // 评估所有条件
    public static boolean evaluate(FilterGroup filterGroup, JSONObject json) {
        boolean andResult = evaluateAndConditions(filterGroup.getFilterAnd(), json);
        boolean orResult = evaluateOrConditions(filterGroup.getFilterOr(), json);
        
        // 如果AND条件为空，只看OR条件；如果OR条件为空，只看AND条件
        if (filterGroup.getFilterAnd() == null || filterGroup.getFilterAnd().isEmpty()) {
            return orResult;
        }
        if (filterGroup.getFilterOr() == null || filterGroup.getFilterOr().isEmpty()) {
            return andResult;
        }
        
        return andResult && orResult;
    }
    
    // 评估AND条件组
    private static boolean evaluateAndConditions(List<FilterExpression> conditions, JSONObject json) {
        if (conditions == null || conditions.isEmpty()) {
            return true;
        }
        
        return conditions.stream().allMatch(condition -> evaluateCondition(condition, json));
    }
    
    // 评估OR条件组
    private static boolean evaluateOrConditions(List<FilterExpression> conditions, JSONObject json) {
        if (conditions == null || conditions.isEmpty()) {
            return true;
        }
        
        return conditions.stream().anyMatch(condition -> evaluateCondition(condition, json));
    }
    
    // 评估单个条件
    public static boolean evaluateCondition(FilterExpression condition, JSONObject json) {
        Object leftValue = json.get(condition.getLeftPath());
        Object rightValue = condition.getRightPath() != null ? 
        		json.get(condition.getRightPath()) : 
                condition.getRightValue();
        
        boolean pass = compare(leftValue, condition.getOperator(), rightValue);
        log.debug("rule:{}{}{} return:{}", leftValue, condition.getOperator(), rightValue, pass);
                
		return pass;
    }
    
    // 比较两个值
    private static boolean compare(Object leftValue, String operator, Object rightValue) {
    	// is null和is not null作特殊判断
    	if ("is not null".equals(operator)) {
    		return leftValue != null;
    	} else if ("is null".equals(operator)) {
    		return leftValue == null;
    	}
    	
    	// 处理值为null的情况
        if (leftValue == null && rightValue == null) {
            return operator.equals("=") || operator.equals("==");
        } else if (leftValue == null || rightValue == null) {
            return operator.equals("!=");
        }
        
        switch (operator) {
            case "=":
            case "==":
                return compareValues(leftValue, rightValue) == 0;
            case "!=":
                return compareValues(leftValue, rightValue) != 0;
            case ">":
                return compareValues(leftValue, rightValue) > 0;
            case "<":
                return compareValues(leftValue, rightValue) < 0;
            case ">=":
                return compareValues(leftValue, rightValue) >= 0;
            case "<=":
                return compareValues(leftValue, rightValue) <= 0;
            case "equals":
                String v1 = String.valueOf(leftValue);
                String v2 = String.valueOf(rightValue);
                return v1.equals(v2);
            default:
                throw new IllegalArgumentException("Unsupported operator: " + operator);
        }
    }
    
    public static void main(String[] args) {
    	Integer lv = 0;
    	String rv = "1";
		System.err.println(compareValues(lv, rv)==0);
	}
    
    // 比较值大小
    private static double compareValues(Object val1, Object val2) {
    	if (val1 instanceof String && val2 instanceof String) {
    		String v1 = String.valueOf(val1);
    		String v2 = String.valueOf(val2);
    		return Objects.equals(v1, v2) ? 0 : 1;
    	} else {
	    	BigDecimal v1 = new BigDecimal(val1.toString());
	    	BigDecimal v2 = new BigDecimal(val2.toString());
	    	return v1.subtract(v2).doubleValue();
    	}
    }
}
